lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

Lecture 7_ exploitation techniques.md (7896B)


      1 +++
      2 title = "Lecture 7: exploitation techniques"
      3 +++
      4 
      5 # Lecture 7: exploitation techniques
      6 ## Buffer overflows:
      7 - common mistake
      8 - can exploit locally and remotely
      9 - can modify both data and control flow
     10 - architecture and OS version dependent
     11 - example buffer overflow was contiguous, arbitrary-length, null-terminated, stack-based. variations in these are possible.
     12 - typical signs of buffer overflows: fixed-length buffers, passing pointer to buffer without size, array access without size check, pointer arithmetic without size/end pointer
     13 - vulnerable functions:
     14     - `gets()` reads up to newline - replace with `fgets()`
     15     - `strcpy()`/`strcat()` copies up to null byte - replace with `strncpy()`/`strncat()`
     16     - `sprintf()` etc. length depends on format arguments - replace with `snprintf()` etc.
     17     - `scanf()` etc. length depends on input string - put bound on `%s` formats
     18     - own input functions might be sloppy, always check assumptions
     19 
     20 ## Array overflow (provides arbitrary write)
     21 
     22 ```c
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 int main(int argc, char **argv) {
     26     long array[8];
     27     long index = strtol(argv[1], NULL, 10);
     28     long value = strtoul(argv[2], NULL, 16);
     29     array[index] = value;
     30     return 0;
     31 }
     32 ```
     33 You can load shellcode into environment, then write to this array to overwrite the return address.
     34 
     35 
     36 ## Off-by-one errors
     37 - e.g. wrong comparison operator, forget about string terminator
     38 - similar to regular overflows, but can overwrite only one element above array size
     39 - this can be exploited to overflow adjacent buffers
     40 - note: every pointer contains 2 null bytes (at end in 64-bit, integers are stored little endian)
     41 
     42 ## Data/BSS overflows
     43 Data and BSS store global variables
     44 No return address reachable for contiguous overflows.
     45 What can you do?
     46 - overwriting function pointer
     47 - overwrite saved frame pointer (attacker can set up fake stack, later return from this stack)
     48 - overwrite C++ object pointer (can hijack virtual function calls)
     49 - overwriting variables often breaks security, like changing strings/integers
     50 - changing pointers
     51 
     52 ## Heap overflows
     53 explicit allocation functions return memory on heap, which survives function return but needs explicit deallocation.
     54 harder to exploit: no return addresses, relative locations depend on order and malloc implementation
     55 instead you target e.g. metadata
     56 
     57 heap organisation:
     58 - heap grows towards higher memory address
     59 - memory managed through in-band control structures (metadata is between buffers)
     60 - control structures can be manipulated through heap overflows for arbitrary code execution
     61 - depends on architecture and OS (especially libc)
     62 - heap is divided in chunks, adjacent free blocks are merged
     63 
     64 dlmalloc (used in glibc) implementation:
     65 1. find free chunk from free list
     66     - if not found, allocate more memory from OS and add to free list
     67 2. if chunk too large, split in two and add new chunk to free list
     68 3. Remove chunk from free list
     69 4. Mark chunk as used in metadata
     70 5. Return pointer to data area in chunk
     71 
     72 dlmalloc's free:
     73 1. Locate chunk with data pointer
     74 2. Mark chunk as free in metadata
     75 3. If next chunk also free, merge with next chnk
     76 4. If previous chunk also free, merge with previous chunk
     77 5. Add chunk to free list
     78 
     79 Metadata at start of every chunk:
     80 
     81 ```c
     82 struct malloc_chunk {
     83     size_t prev_size;
     84     size_t size;
     85     struct malloc_chunk* fd; // used only if free, otherwise data pointer starts here
     86     struct malloc_chunk* bk;
     87 };
     88 ```
     89 
     90 Chunk size:
     91 - 8 bytes overhead per allocated block (only size field always used)
     92 - size always multiple of 16 (data size+overhead rounded up, four low-order bits always 0)
     93 - low-order bits of size field used for status
     94 
     95 Free list:
     96 - used to find free block to allocate
     97 - doubly linked list using `fd` and `bk` fields
     98 - insertion in free list: free(), splitting large block in malloc
     99 - removal from free list: malloc(), merging free blocks in free()
    100 
    101 Exploiting dlmalloc:
    102 - assume we find heap buffer overflow
    103 - overwrite `fd` and `bk` (requires free block)
    104 - make program call unlink (e.g. to merge block when block before is freed)
    105 - unlink writes chosen data (`fd`) at chosen location (`bk`)
    106 
    107 In stack buffer overflows, return address is at fixed offset (so it's easy to reach)
    108 Heap overflow/format string write to an absolute address
    109 Alternative target is Global Offset Table
    110 - used to lazily load library functions
    111 - address is looked up and stored on first call
    112 - has a fixed location
    113 - can use printf
    114 
    115 
    116 ## Integer overflow
    117 Integers have a fixed size, each integer type has limited range.
    118 If result does not fit in range of integer, CPU still computes result but discards bits that don't fit
    119 Classification:
    120 - truncation: integer is cast to a smaller type, discarding extra bits
    121 - arithmetic overflow: computation result out of range for type, wrapping around
    122 - signedness: negative integer cast to unsigned type, incorrectly interpreting sign bit
    123 
    124 ## Format strings
    125 printf and related take format string and parameters
    126 careless programmers might let user specify format string
    127 
    128 parameter passing is just like for other functions (registers, then stack)
    129 missing parameters filled with whatever happened to be there -- information leaks, or position to reach all of stack
    130 `%n` - writes to memory, stores number of output characters so far to pointer passed as parameter. so controlling format strings implies arbitrary write.
    131 
    132 ```c
    133 int main(int argc, char **argv) {
    134     char buf[256];
    135     int y = 1;
    136     snprintf(buf, sizeof(buf), argv[1]); // missing parameter! so format string is attacker-controlled
    137     printf("buffer (%d): %s\n", strlen(buf), buf);
    138     printf("y is %d/0x%x (@ %p)\n", y, y, &y);
    139     return 0;
    140 }
    141 ```
    142 
    143 ## Temporal errors
    144 Spatial errors let attacker access outside space allocated for buffer.
    145 Temporal errors let attacker access buffer before/after intended time frame
    146 Main types;
    147 - use after free
    148 - uninitialized variables
    149 
    150 Use after free:
    151 - sometimes program retains pointer to freed memory location
    152     - malloc buffer that was freed
    153     - local variable/alloca buffer after function return
    154 - future allocation/function call can re-use memory
    155 - dereferencing dangling pointer results in undefined behavior
    156 - attacker can craft input to overwrite memory with own data
    157     1. program allocates X
    158     2. program uses X to store some data
    159     3. program frees X
    160     4. program allocates Y overlapping with X
    161     5. data written to Y also overwrites relevant part of X
    162     6. program uses X, causing incorrect result
    163 
    164 Uninitialized variables
    165 - local variables and malloc buffers not automatically zeroed
    166 - instead contain whatever happened to be there
    167 - compilers try to warn, but e.g. arrays, struct/union members, malloc buffers not checked
    168 - attacker can initialize variable in way that programmer didn't expect:
    169     1. program allocates X
    170     2. program uses X to store data under attacker control
    171     3. program frees X
    172     4. program allocates Y overlapping X
    173     5. program doesn't initialize some/all of Y, causing attacker-provided data from X to stay there
    174     6. program uses Y, causing incorrect result
    175 
    176 ## Type confusion
    177 C++ provides classes (basically structs tying data to functions)
    178 Instance of class is object, can be on stack or on heap
    179 Classes can inherit from one or more classes, can call all functions available from parent.
    180 Object pointer can be cast from child to parent.
    181 
    182 C++ typecasts:
    183 - reinterpret_cast: no checks (fast), assumes programmer knows their shit (unsafe)
    184 - static_cast: compile-time check (fast at runtime), allows any possibly valid cast including parent-to-child (still unsafe)
    185 - dynamic_cast: run-time check (slow), ensures runtime type is consistent with compile-time type (safe)
    186 
    187 static_cast is common but unsafe:
    188 - object may be cast to wrong type
    189 - incorrect cast causes mismatch between runtime type and compile-time type, members read/written according to wrong type